<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>依赖注入</title>
    <script src="../public/vue_3.2.36.js"></script>
  </head>
  <body>
    <div id="app" style="background-color: yellowgreen; padding: 10px">
      <h2>app组件</h2>
      msg的值-------------{{msg}}
      <hr>
      count的值-------------{{count}}
      <child hh="hello"></child>
    </div>
    <template id="child">
      <div style="background-color: red; padding: 6px">
        <h2>child组价</h2>
        <div>这是child组件(通过props传递):<strong>{{props.hh}}</strong></div>
        <son></son>
      </div>
    </template>
    <template id="son">
      <div style="background-color: aqua">
        <h2>son组件</h2>
        这是son组件（inject接收）:<strong>{{message.msg}}</strong>
        <button @click="message.changeMsg('小雨哥哥')">点击更改哈</button>
        <hr>
        <button @click="count++">点击count++</button>
      </div>
    </template>
    <script>
      const { createApp, ref, provide, inject ,readonly } = Vue;
      const son = {
        template: "#son",
        setup() {
          const message = inject("message");
          const count=inject("read-only-count");
          return { message ,count};
        },
      };
      const child = {
        template: "#child",
        components: { son },
        props: ["hh"],
        setup(props) {
          return { props };
        },
      };
      const app = createApp({
        components: { child },
        setup() {
          /* 
            有的时候，我们可能需要在注入方组件中更改数据。
            在这种情况下，我们推荐在供给方组件内声明并提供一个更改数据的方法函数：
            */
          const msg = ref("hello");
          const changeMsg = function (val) {
            msg.value = val;
          };
          provide("message", { msg, changeMsg }); //这里在APP组件上进行了依赖提供。
          /* 
          如果你想确保提供的数据不能被注入方的组件更改，你可以使用 readonly() 来包装提供的值。
          */
          const count = ref(1);
          provide("read-only-count", readonly(count));
          return { msg, count };
        },
      });
      app.mount("#app");
    </script>
  </body>
</html>
